<template>
  <view :style="[customStyle]" class="u-subform">
    <view class="u-subform-item" v-for="(dataItem, index) in currentDataSource">
      <view class="u-subform-order"
        ><view class="order-style">{{ index + 1 }}</view>
        <view class="u-subform-feature">
          <view class="feature-item" @click="optionsHandler('delete', index)">删除</view>
          <view class="feature-item" @click="optionsHandler('copy', index)">复制</view>
          <view class="feature-item" @click="showMoreFeature(index)"
            >更多 <u-icon name="arrow-down"
          /></view>
          <u-select
            v-model="featureMoreVisible"
            :list="featureMoreList"
            @confirm="handleConfirm"
            @cancel="handleCancel"
          ></u-select>
        </view>
      </view>
      <view class="u-subform-main" @mouseover="() => handleMouseover(index)">
        <slot :dataItem="dataItem" :index="index"></slot>
      </view>
    </view>
    <u-button custom-style="border:0;" :hair-line="false" @click="optionsHandler('add')"
      ><u-icon name="plus" />增加</u-button
    >
  </view>
</template>

<script>
  import mpConfig from '../../libs/mixin/mp-vertual-node.js';
  /**
   * u-subform 子表单
   * @description 封装子表单
   * @property {Array<Record<string,any>>} dataSource 值
   * @property {Boolean} editState 编辑模式
   * @property {Boolean} disabled 是否禁用(默认false)
   */
  export default {
    name: 'u-subform',
    options: mpConfig,
    emits: ['update:dataSource', 'update:current', 'update:currentIndex'],
    props: {
      editState: {
        type: Boolean,
        default: false,
      },
      dataSource: {
        type: Array,
        default: () => [],
      },
      disabled: {
        type: Boolean,
        default: false,
      },
    },
    data() {
      return {
        currentDataSource: this.$u.deepClone(this.dataSource),
        originalDataSource: this.$u.deepClone(this.dataSource),
        featureMoreVisible: false,
        currentRowIndex: -1,
        featureMoreList: [
          {
            value: 'copyToEnd',
            label: '复制到最后1行',
          },
          {
            value: 'insertBefore',
            label: '向上插入1行',
          },
          {
            value: 'insertAfter',
            label: '向下插入1行',
          },
        ],
      };
    },
    computed: {
      dataSourceItem() {
        // 以第一行数据作为模板构建数据
        const templateData = this.dataSource[0] || {};
        const defaultDataSource = {};
        // 根据原始数据类型设置初始值
        Object.keys(templateData).forEach((key) => {
          defaultDataSource[key] = '';
          if (Array.isArray(templateData[key])) {
            defaultDataSource[key] = [];
          }
          if (typeof templateData[key] === 'number' || typeof templateData[key] === 'undefined') {
            defaultDataSource[key] = undefined;
          }
          if (templateData[key] === null) {
            defaultDataSource[key] = null;
          }
        });
        return defaultDataSource;
      },
    },
    watch: {
      currentDataSource: {
        handler(newValue) {
          this.$emit('update:dataSource', newValue);
        },
        deep: true,
      },
      dataSource: {
        handler(newValue) {
          this.currentDataSource = this.$u.deepClone(newValue);
        },
        deep: true,
      },
    },
    mounted() {},
    methods: {
      // 数据源置空，还原到初始值状态
      resetDataSource() {
        this.currentDataSource = this.$u.deepClone(this.originalDataSource);
      },
      getDefaultDataSource() {
        return Object.assign({}, this.dataSourceItem);
      },
      optionsHandler(type, index = -1) {
        // 禁用点击
        if (this.disabled) {
          return;
        }
        if (index === -1 && type === 'add') {
          this.currentDataSource.push(Object.assign({}, this.getDefaultDataSource()));
        } else {
          const formData = Object.assign({}, this.currentDataSource[index]);
          // 复制时不复制id
          if (formData && formData.id) {
            delete formData.id;
          }
          switch (type) {
            case 'delete':
              this.currentDataSource.splice(index, 1);
              break;
            case 'copy':
              this.currentDataSource.splice(index, 0, formData);
              break;
            case 'copyToEnd':
              this.currentDataSource.push(formData);
              break;
            case 'insertBefore':
              this.currentDataSource.splice(
                index,
                0,
                Object.assign({}, this.getDefaultDataSource()),
              );
              break;
            case 'insertAfter':
              this.currentDataSource.splice(
                index + 1,
                0,
                Object.assign({}, this.getDefaultDataSource()),
              );
              break;
          }
        }
      },
      handleConfirm(options) {
        const [option] = options;
        this.optionsHandler(option.value, this.currentRowIndex);
      },
      handleCancel() {
        this.currentRowIndex = -1;
      },
      showMoreFeature(index) {
        this.currentRowIndex = index;
        this.featureMoreVisible = true;
      },
      handleMouseover(index) {
        this.$emit('update:currentIndex', index);
        this.$emit('update:current', this.currentDataSource[index]);
      },
    },
  };
</script>

<style scoped lang="scss">
  @import '../../libs/css/style.components.scss';

  .u-subform {
    /* #ifndef APP-NVUE */
    display: block;
    /* #endif */
    width: 100%;
    border-radius: 10rpx;
    border: 1px solid #c0c4cc;
    .u-subform-item {
      border-bottom: 1px solid #c0c4cc;
      padding: 16rpx;
      .u-subform-order {
        display: flex;
        flex-direction: row;
        justify-content: space-between;
        .order-style {
          width: 1.6em;
          height: 1.6em;
          line-height: 1.6em;
          margin-top: 0.3em;
          border-radius: 100%;
          font-weight: bold;
          color: #fff;
          background: $u-type-primary;
          text-align: center;
        }
        .u-subform-feature {
          display: flex;
          color: $u-type-primary;
          .feature-item {
            margin: 0 0.5em;
          }
        }
      }
    }
    :deep(.u-form-item) {
      padding: 0;
    }
  }
</style>
